package cn.angetech.linkis.gateway.ujes;

import cn.angetech.linkis.core.common.ServiceInstance;
import cn.angetech.linkis.core.common.conf.BDPConfiguration;
import cn.angetech.linkis.core.common.exception.DWCException;
import cn.angetech.linkis.core.common.utils.Utils;
import cn.angetech.linkis.core.module.conf.ServerConfiguration;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;


@SpringBootApplication
public class CloudApplication extends SpringBootServletInitializer {
    private static final Log logger = LogFactory.getLog(CloudApplication.class);
    private static ConfigurableApplicationContext applicationContext;
    private static ServiceInstance serviceInstance;


    public static void main(String[] args) throws ReflectiveOperationException{
        // 平时的启动
//         SpringApplication.run(CloudApplication.class,args);

        // 通过加载配置的启动
        final SpringApplication application = new SpringApplication(CloudApplication.class);
        application.addListeners(new ApplicationListener<ApplicationPreparedEvent>(){
            public void onApplicationEvent(ApplicationPreparedEvent applicationPreparedEvent) {
                logger.info("main=====================================================add config from config server...");
                if(applicationContext == null) {
                    applicationContext = applicationPreparedEvent.getApplicationContext();
                    logger.info(applicationContext);
                }
                addRemoteConfig();
                logger.info("main=====================================================initialize DataWorkCloud spring application...");
                initDWCApplication();
            }
        });

        application.addListeners(new ApplicationListener<RefreshScopeRefreshedEvent>() {
            public void onApplicationEvent(RefreshScopeRefreshedEvent applicationEvent) {
                logger.info("main=====================================================refresh config from config server...");
                updateRemoteConfig();
            }
        });

        String listeners = ServerConfiguration.BDP_SERVER_SPRING_APPLICATION_LISTENERS().getValue();
        if(StringUtils.isNotBlank(listeners)) {
            for (String listener : listeners.split(",")) {
                application.addListeners((ApplicationListener<?>) Class.forName(listener).newInstance());
            }
        }
        applicationContext = application.run(args);


    }
    public static void updateRemoteConfig() {
        addOrUpdateRemoteConfig(applicationContext.getEnvironment(), true);
    }
    public static void addRemoteConfig() {
        addOrUpdateRemoteConfig(applicationContext.getEnvironment(), false);
    }
    private static void addOrUpdateRemoteConfig(Environment env, boolean isUpdateOrNot) {
        StandardEnvironment environment = (StandardEnvironment) env;
        PropertySource propertySource = environment.getPropertySources().get("bootstrapProperties");
        if(propertySource == null) {
            return;
        }
        CompositePropertySource source = (CompositePropertySource) propertySource;
        for (String key: source.getPropertyNames()) {
            Object val = source.getProperty(key);
            if(val == null) {
                continue;
            }
            if(isUpdateOrNot) {
                logger.info("update remote config => " + key + " = " + source.getProperty(key));
                BDPConfiguration.set(key, val.toString());
            } else {
                logger.info("add remote config => " + key + " = " + source.getProperty(key));
                BDPConfiguration.setIfNotExists(key, val.toString());
            }
        }
    }

    private static void initDWCApplication() {
        serviceInstance = new ServiceInstance();
        serviceInstance.setApplicationName(applicationContext.getEnvironment().getProperty("spring.application.name"));
        serviceInstance.setInstance(Utils.getComputerName() + ":" + applicationContext.getEnvironment().getProperty("server.port"));
        DWCException.setApplicationName(serviceInstance.getApplicationName());
        DWCException.setHostname(Utils.getComputerName());
        DWCException.setHostPort(Integer.parseInt(applicationContext.getEnvironment().getProperty("server.port")));
    }


}
